package com.dahuyou.nio.discard.server.server;

import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

/**
 * nio discard server服务端
 */
public class NioDiscardServer {

    public static void main(String[] args) throws Exception {
        // 1：打开选择器
        Selector selector = Selector.open();
        // 2：获取通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 3：设置为非阻塞(阻塞了也就失去了nio的意义了！并且只有非阻塞才支持绑定事件)
        serverSocketChannel.configureBlocking(false);
        // 4：绑定链接
        serverSocketChannel.bind(new InetSocketAddress(18899));
        // 5：注册io事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服务器启动成功");

        // 6：阻塞方式轮询感兴趣的通道事件(IO就绪)
        while (selector.select() > 0) {
            // 7：获取封装事件+通道的选择键的集合
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                // 8：获取某个选择键进行处理
                SelectionKey selectionKey = iterator.next();
                // 9：判断具体的事件，并进行处理
                if (selectionKey.isAcceptable()) {
                    System.out.println("新连接来了：" + selectionKey.channel());
                    // 10：就绪事件，获取客户端的链接(一个个来建立链接？？？可能不是个问题！！！不太明白这里为什么
                    // 这么写？？？)
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    // 11：设置为非阻塞
                    socketChannel.configureBlocking(false);
                    // 12：注册到选择器监听相关事件
//                    SelectionKey register = socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT);
                    socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE | SelectionKey.OP_CONNECT);
                }
                // 可写事件
                if (selectionKey.isWritable()) {
                    System.out.println("可写啦，" + selectionKey.channel());
                }
                if (selectionKey.isConnectable()) {
                    System.out.println("连接成功啦，" + selectionKey.channel());
                }
                if (selectionKey.isReadable()) {
                    System.out.println("数据可读啦，" + selectionKey.channel());
                    // 13：获取通道，为读取数据做准备啦
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    // 14：读取数据啦
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    int length = 0;
                    while ((length = socketChannel.read(byteBuffer)) > 0) {
                        // 转成读模式
                        byteBuffer.flip();
                        System.out.println("读取到数据：" + new String(byteBuffer.array(), 0, length));
                        // 恢复成写模式(这里其实不用的，但当个好习惯吧！)
                        byteBuffer.clear();
                    }
                    System.out.println("discard 啦！！！！！！！！！！！！");
                    // 读完消息了，就discard(discard server的体现指出)
                    socketChannel.close();

                }
                // 15：移出选择键，防止重复处理
                iterator.remove();
            }
        }
        // 关闭链接(这里应该是执行不到的，因为selector.select啦)
        serverSocketChannel.close();
    }


}
